package com.yumo.kangchenjunga.security;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint;
import org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

@EnableWebSecurity
public class SecurityConfig {
	
	@Configuration
	@Order(1)
	public class CompanyConfigurationAdapter extends WebSecurityConfigurerAdapter {

		@Override
		public void configure(WebSecurity web) throws Exception {
			web.ignoring()
				.antMatchers("/**/css/**", "/**/js/**", "/**/plugins/**", "/**/images/**",
	        		"/403", "/404", "/500");
		}
		
		@Override
	    public void configure(AuthenticationManagerBuilder auth) throws Exception {
	        auth.userDetailsService(customUserDetailsService()).passwordEncoder(passwordEncoder())
	        	.and().inMemoryAuthentication().withUser("user").password("password").roles("company_admin");
	    }
	
		@Override
		public void configure(HttpSecurity http) throws Exception {
			http
//				.authorizeRequests()
//        		.antMatchers("/company/**").hasAnyRole("COMPANY_ADMIN", "COMPANY_POWER_USER", "COMPANY_USER")
//            	.antMatchers("/api/v1/**").authenticated()
//	            	.anyRequest().authenticated()
//	            	.and()
	            .antMatcher("/company/**")
	            	.authorizeRequests()
	            	.anyRequest()
	            	.hasAnyRole("COMPANY_ADMIN", "COMPANY_POWER_USER", "COMPANY_USER", "STORE_ADMIN", "STORE_POWER_USER", "STORE_USER")
	            	.and()
	            .addFilterBefore(usernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
	            .formLogin()
	            	.loginPage("/company/login")
	            	.permitAll()
	            	.and()
	        	.logout()
					.logoutUrl("/company/logout")
					.logoutSuccessUrl("/company/login")
		            .permitAll()
		            .and()
	            .exceptionHandling()
	            .defaultAuthenticationEntryPointFor(
	        		companyloginUrlauthenticationEntryPoint(), new AntPathRequestMatcher("/company/**"))
	            	.accessDeniedPage("/403");
			http.csrf().disable();
	        http.headers().frameOptions().sameOrigin();
		}
		

	    @Bean
	    public CustomUsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter() throws Exception {
	    	CustomUsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new CustomUsernamePasswordAuthenticationFilter();
	    	usernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
	    	usernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(new CustomSavedRequestAwareAuthenticationSuccessHandler("/company/"));
	    	usernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/company/login?error"));
	    	return usernamePasswordAuthenticationFilter;
	    }
	
	}
	
	@Configuration
	@Order(2)
	public class AdminConfigurationAdapter extends WebSecurityConfigurerAdapter {
		
		@Override
	    public void configure(WebSecurity web) {
			web.ignoring()
				.antMatchers("/**/css/**", "/**/js/**", "/**/plugins/**", "/**/images/**",
	        		"/403", "/404", "/500");
	    }
		
		@Override
	    public void configure(AuthenticationManagerBuilder auth) throws Exception {
	        auth.userDetailsService(customUserDetailsService()).passwordEncoder(passwordEncoder())
	        	.and().inMemoryAuthentication().withUser("user").password("password").roles("admin");
	    }
	 
	    @Override
		protected void configure(HttpSecurity http) throws Exception {
	        http
//		        .authorizeRequests()
//		    		.antMatchers("", "")
//		    		.permitAll().anyRequest().authenticated()
//		    		.and()
//		        	.antMatchers("/admin/**").hasAnyRole("ADMIN", "POWER_USER", "USER")
//		        	.antMatchers("/api/v1/**").authenticated()
//		            .anyRequest().authenticated()
//	            	.and()
	        	.antMatcher("/admin/**")
	        		.authorizeRequests()
	        		.anyRequest()
	        		.hasAnyRole("ADMIN", "POWER_USER", "USER")
	        		.and()
            	.addFilterBefore(adminUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
	            .formLogin()
	            	.loginPage("/admin/login")
	            	.permitAll()
	            	.and()
            	.logout()
					.logoutUrl("/admin/logout")
					.logoutSuccessUrl("/admin/login")
		            .permitAll()
		            .and()
		        .exceptionHandling()
	            .defaultAuthenticationEntryPointFor(
            		adminloginUrlauthenticationEntryPoint(), new AntPathRequestMatcher("/admin/**"))
	            	.accessDeniedPage("/403");
	        http.csrf().disable();
	        http.headers().frameOptions().sameOrigin();
	    }
	    
	    @Bean
	    public CustomAdminUsernamePasswordAuthenticationFilter adminUsernamePasswordAuthenticationFilter() throws Exception {
	    	CustomAdminUsernamePasswordAuthenticationFilter usernamePasswordAuthenticationFilter = new CustomAdminUsernamePasswordAuthenticationFilter();
	    	usernamePasswordAuthenticationFilter.setAuthenticationManager(authenticationManager());
	    	usernamePasswordAuthenticationFilter.setAuthenticationSuccessHandler(new CustomSavedRequestAwareAuthenticationSuccessHandler("/admin/customers"));
	    	usernamePasswordAuthenticationFilter.setAuthenticationFailureHandler(new SimpleUrlAuthenticationFailureHandler("/admin/login?error"));
	    	return usernamePasswordAuthenticationFilter;
	    }
	}
	
	@Configuration
	@Order(3)
	public class GlobalConfigurationAdapter extends WebSecurityConfigurerAdapter {

		@Override
	    public void configure(WebSecurity web) {
	        web.ignoring()
	        	.antMatchers("/**/css/**", "/**/js/**", "/**/plugins/**", "/**/images/**",
	        		"/403", "/404", "/500", "/api/v1/companies/getStoreByCompanyId/**");
	    }
		
	    @Override
		protected void configure(HttpSecurity http) throws Exception {
	        http
	        	.authorizeRequests()
	        	.antMatchers("/api/v1/**")
	        	.authenticated();
	        http.csrf().disable();
	        http.headers().frameOptions().sameOrigin();
	    }
	}
	
	@Bean
    public CustomUserDetailsService customUserDetailsService() {
    	return new CustomUserDetailsService();
    }

    @Bean
    public CustomUserPasswordEncoder passwordEncoder() {
    	return new CustomUserPasswordEncoder();
    }
    
    @Bean
    public AuthenticationEntryPoint companyloginUrlauthenticationEntryPoint(){
        return new LoginUrlAuthenticationEntryPoint("/company/login");
    }
    
    @Bean
    public AuthenticationEntryPoint adminloginUrlauthenticationEntryPoint(){
        return new LoginUrlAuthenticationEntryPoint("/admin/login");
    }

}
